package com.wufun.overseas.view.header;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.animation.AccelerateInterpolator;

import com.wufun.overseas.R;
import com.wufun.overseas.view.ptr.PtrFrameLayout;
import com.wufun.overseas.view.ptr.PtrUIHeader;
import com.wufun.overseas.view.ptr.indicator.PtrIndicator;
import com.wufun.overseas.view.ptr.indicator.PtrTensionIndicator;


/**
 * Created by xiet on 2016/4/13.
 */
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class DropBounceHeaderView extends PtrUIHeader {

    private final String TAG = "DropBounceHeaderView";

    private PtrFrameLayout mPtrFrameLayout;
    private PtrTensionIndicator mPtrTensionIndicator;

    private AnimationDrawable mAnimationDrawable;

    private Path mCirclePath;
    private Paint mCirclePaint;

    float mMargin = 1;//不加图像会有明显抖动
    float mScale  = 0.8f;
//    float mScale  = 1.f;

    private float mDropCircleRadius = 100f;//def
    private RectF mDropRect;
    private int   mMaxDropHeight;
    private int   mWidth;
    private int mColor = Color.WHITE;

    private int mBounceFlag = 0;//0-expansion countour, 1-start
    private float mCurrentCircleCenterY;
    private boolean mIsStartDropCircle = false;

    private ValueAnimator mDropBounceVerticalAnimator;
    private ValueAnimator mDropBounceHorizontalAnimator;
    private ValueAnimator mDropCircleAnimator;
    private ValueAnimator mScaleCircleAnimator;

    private ValueAnimator.AnimatorUpdateListener mAnimatorUpdateListener =
            new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator valueAnimator) {
                    postInvalidate();
                }
            };

    //region Construct
    public DropBounceHeaderView(Context context) {
        super(context);
        init();
    }

    public DropBounceHeaderView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public DropBounceHeaderView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        Resources res = getResources();

        mDropRect = new RectF();

        mAnimationDrawable = (AnimationDrawable) res.getDrawable(R.drawable.loading_animation1);
//        mAnimationDrawable = new DropBounceDrawable(getContext());
        setBackgroundDrawable(mAnimationDrawable);
        mDropCircleRadius = mAnimationDrawable.getIntrinsicHeight() * mScale / 2;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            setLayerType(View.LAYER_TYPE_SOFTWARE, null);//离屏缓冲
        }

        setUpPaint();
        setUpPath();
        resetAnimator();
    }

    private void resetAnimator() {
        clearListeners(mDropBounceHorizontalAnimator);
        clearListeners(mDropBounceVerticalAnimator);
        clearListeners(mDropCircleAnimator);
        clearListeners(mScaleCircleAnimator);
        mDropBounceVerticalAnimator = ValueAnimator.ofFloat(0.f, 0.f);
        mDropBounceHorizontalAnimator = ValueAnimator.ofFloat(0.f, 0.f);
        mDropCircleAnimator = ValueAnimator.ofFloat(0.f, 0.f);
        mDropCircleAnimator.start();
        mScaleCircleAnimator = ValueAnimator.ofFloat(0.f, 0.f);
        mScaleCircleAnimator.setDuration(1); // immediately finish animation cycle
        mScaleCircleAnimator.start();
    }

    private void clearListeners(ValueAnimator animator) {
        if (animator != null && animator.getListeners() != null) {
            animator.getListeners().clear();
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int height = (int) (mAnimationDrawable.getIntrinsicHeight() * mScale);
        heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(height + getPaddingTop() + getPaddingBottom(), View.MeasureSpec.EXACTLY);

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    private void setUpPath() {
        mCirclePath = new Path();
    }

    private void setUpPaint() {
        mCirclePaint = new Paint();
        mCirclePaint.setTextSize(22);
        mCirclePaint.setColor(mColor);
        mCirclePaint.setAntiAlias(true);
        mCirclePaint.setStyle(Paint.Style.FILL);//设置实心

    }

    public void setUp(PtrFrameLayout ptrFrameLayout) {
        mPtrFrameLayout = ptrFrameLayout;
        mPtrTensionIndicator = new PtrTensionIndicator();
        mPtrFrameLayout.setPtrIndicator(mPtrTensionIndicator);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
//        Logger.log(TAG, "onSizeChanged", "w=" + w + " h=" + h + " oldw=" + oldw + " oldh=" + oldh);
        mWidth = w;
        super.onSizeChanged(w, h, oldw, oldh);
    }

    //endregion


    @Override
    protected void onDraw(Canvas canvas) {

        mCirclePath.reset();
        mDropRect.setEmpty();

        float left   = 0.f;
        float top    = 0.f;
        float right  = 0.f;
        float bottom = 0.f;

        float circleCenterY = (Float) mDropCircleAnimator.getAnimatedValue();
        mCurrentCircleCenterY = circleCenterY;
        float circleCenterX = mWidth / 2.f;
        float scale         = (Float) mScaleCircleAnimator.getAnimatedValue();
        float vertical      = (Float) mDropBounceVerticalAnimator.getAnimatedValue();
        float horizontal    = (Float) mDropBounceHorizontalAnimator.getAnimatedValue();
        float flag          = mBounceFlag;
        left = circleCenterX - mDropCircleRadius * (1 + vertical * flag) * scale + mDropCircleRadius * horizontal / 2;
        top = circleCenterY + mDropCircleRadius * (1 + horizontal * flag) * scale - mDropCircleRadius * vertical / 2;
        right = circleCenterX + mDropCircleRadius * (1 + vertical * flag) * scale - mDropCircleRadius * horizontal / 2;
        bottom = circleCenterY - mDropCircleRadius * (1 + horizontal * flag) * scale + mDropCircleRadius * vertical / 2;

        //margin
        float margin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mMargin, getResources().getDisplayMetrics());
        left += margin / 2.f;
        top += margin;
        right -= margin / 2.f;

//        Logger.log(TAG, "onDraw", "centerY=" + circleCenterY + " scale=" + scale + " vertical=" + vertical + " horizontal=" + horizontal);
//        Logger.log(TAG, "onDraw", "left= " + left + " top=" + top + " right=" + right + " bottom=" + bottom);
        mDropRect.set(left, top, right, bottom);
        mCirclePath.addOval(mDropRect, Path.Direction.CCW);

        canvas.drawPath(mCirclePath, mCirclePaint);

        //papa monkey
        if (mAnimationDrawable.isRunning()) {
            float paMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2.f, getResources().getDisplayMetrics());
            int   paLeft   = (int) (left + paMargin);
            int   paTop    = (int) (bottom + paMargin);
            int   paRight  = (int) (right - paMargin);
            int   paBottom = (int) (top - paMargin);
            mAnimationDrawable.setBounds(paLeft, paTop, paRight, paBottom);
            Drawable currentDrawable = mAnimationDrawable.getCurrent();
            currentDrawable.draw(canvas);
        } else {
            mAnimationDrawable.setBounds(0, 0, 0, 0);
        }

        if (!mDropBounceHorizontalAnimator.isRunning()
                && !mDropBounceVerticalAnimator.isRunning()
                && !mScaleCircleAnimator.isRunning()
                && !mDropCircleAnimator.isRunning()) {
            resumeAnotherRequest();
        }

        super.onDraw(canvas);

    }

    //region animation
    @Override
    protected void onDetachedFromWindow() {
        if (mScaleCircleAnimator != null) {
            mScaleCircleAnimator.end();
            mScaleCircleAnimator.removeAllUpdateListeners();
        }
        if (mDropCircleAnimator != null) {
            mDropCircleAnimator.end();
            mDropCircleAnimator.removeAllUpdateListeners();
        }
        if (mDropBounceHorizontalAnimator != null) {
            mDropBounceHorizontalAnimator.end();
            mDropBounceHorizontalAnimator.removeAllUpdateListeners();
        }
        if (mDropBounceVerticalAnimator != null) {
            mDropBounceVerticalAnimator.end();
            mDropBounceVerticalAnimator.removeAllUpdateListeners();
        }
        super.onDetachedFromWindow();
    }

    private void startDropCircleAnimation() {
        pauseAnotherRequest();
        mIsStartDropCircle = true;

        // show dropBubble again
        mScaleCircleAnimator = ValueAnimator.ofFloat((Float) mScaleCircleAnimator.getAnimatedValue(), 1.f / 3);
        mScaleCircleAnimator.setDuration(200);
        mScaleCircleAnimator.setInterpolator(new AccelerateInterpolator());
        mScaleCircleAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                startReverseCircleAnimation();
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        mScaleCircleAnimator.start();

        mDropBounceHorizontalAnimator = ValueAnimator.ofFloat((Float) mDropBounceHorizontalAnimator.getAnimatedValue(), 0.f);
        mDropBounceHorizontalAnimator.setDuration(200);
        mDropBounceHorizontalAnimator.setInterpolator(new AccelerateInterpolator());
        mDropBounceHorizontalAnimator.start();


        float margin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mMargin, getResources().getDisplayMetrics());
        mDropCircleAnimator = ValueAnimator.ofFloat((Float) mDropCircleAnimator.getAnimatedValue(), getHeight() - 1.f * mDropCircleRadius / 3 - margin / mScale);//- mMargin
        mDropCircleAnimator.setDuration(200);
        mDropCircleAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mCurrentCircleCenterY = (float) animation.getAnimatedValue();
                ViewCompat.postInvalidateOnAnimation(DropBounceHeaderView.this);
            }
        });
        mDropCircleAnimator.setInterpolator(new AccelerateInterpolator());
        mDropCircleAnimator.start();

    }

    private void startBounceAnimation() {
        mBounceFlag = 1;
        long boucne_duration       = 500;
        long boucne_duration_delay = 180;
        mDropBounceVerticalAnimator = ValueAnimator.ofFloat(0.f, 0.5f);
        mDropBounceVerticalAnimator.setDuration(boucne_duration);
        mDropBounceVerticalAnimator.addUpdateListener(mAnimatorUpdateListener);
        mDropBounceVerticalAnimator.setInterpolator(new DropBounceInterpolator());
        mDropBounceVerticalAnimator.setStartDelay(boucne_duration_delay);
        mDropBounceVerticalAnimator.start();

        mDropBounceHorizontalAnimator = ValueAnimator.ofFloat(0.f, 0.1f);
        mDropBounceHorizontalAnimator.setDuration(boucne_duration);
        mDropBounceHorizontalAnimator.addUpdateListener(mAnimatorUpdateListener);
        mDropBounceHorizontalAnimator.setInterpolator(new DropBounceInterpolator());
        mDropBounceHorizontalAnimator.setStartDelay((long) (boucne_duration_delay + boucne_duration * 0.25));
        mDropBounceHorizontalAnimator.start();
    }

    private void startReverseCircleAnimation() {
        if (!mAnimationDrawable.isRunning())
            mAnimationDrawable.start();

        mScaleCircleAnimator = ValueAnimator.ofFloat(1.f / 3, 1.f);
        mScaleCircleAnimator.setDuration(200);
        mScaleCircleAnimator.setInterpolator(new AccelerateInterpolator());
        mScaleCircleAnimator.start();

        float margin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mMargin, getResources().getDisplayMetrics());
        mDropCircleAnimator = ValueAnimator.ofFloat((Float) mDropCircleAnimator.getAnimatedValue(), getHeight() - mDropCircleRadius - margin / mScale);//- mMargin
        mDropCircleAnimator.setDuration(200);
        mDropCircleAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mCurrentCircleCenterY = (float) animation.getAnimatedValue();
                ViewCompat.postInvalidateOnAnimation(DropBounceHeaderView.this);
            }
        });
        mDropCircleAnimator.setInterpolator(new AccelerateInterpolator());
        mDropCircleAnimator.start();

        startBounceAnimation();
    }

    public void setColor(int color) {
        //mColor = Color.parseColor("#4EA9E9");
        mColor = color;

        mCirclePaint.setColor(mColor);
        invalidate();
    }
    //endregion

    private void pauseAnotherRequest() {
//        Glide.with(getContext()).pauseRequests();
    }

    private void resumeAnotherRequest() {
//        Glide.with(getContext()).resumeRequests();
    }

    //region PtrUIHandler
    @Override
    public void onUIReset(PtrFrameLayout frame) {
        Log.d(TAG, "onUIReset method called.");

        resetAnimator();
        mIsStartDropCircle = false;
        if (mAnimationDrawable.isRunning()) {
            mAnimationDrawable.stop();
        }
        invalidate();
    }

    @Override
    public void onUIRefreshPrepare(PtrFrameLayout frame) {
        Log.d(TAG, "onUIRefreshPrepare method called.");
    }

    @Override
    public void onUIRefreshBegin(PtrFrameLayout frame) {
        Log.d(TAG, "onUIRefreshBegin method called.");
    }

    @Override
    public void onUIRefreshComplete(PtrFrameLayout frame) {
        Log.d(TAG, "onUIRefreshComplete method called.");
    }

    @Override
    public void onUIPositionChange(PtrFrameLayout frame, boolean isUnderTouch, byte status, PtrIndicator ptrIndicator) {
        Log.d(TAG, "onUIPositionChange method called.");

        if (mIsStartDropCircle) return;

        float percent = mPtrTensionIndicator.getOverDragPercent();
        float posY    = mPtrTensionIndicator.getCurrentPosY();
        float centerY = (Float) mDropCircleAnimator.getAnimatedValue();
        float scale   = (Float) mScaleCircleAnimator.getAnimatedValue();
//        float vertical   = (Float) mDropBounceVerticalAnimator.getAnimatedValue();
        float horizontal = (Float) mDropBounceHorizontalAnimator.getAnimatedValue();

//        Logger.log(TAG, "onUIPositionChange-Pre", "percent=" + percent + " posY=" + posY + " centerY=" + centerY + " scale=" + scale + " vertical=" + vertical + " horizontal=" + horizontal);

        //高度变化时的动画
        // 0~1/3 画圆形
        if (percent > 0 && percent < (1.0f / 3)) {
            centerY = getHeight() - posY / 2.f;
            scale = percent;
            horizontal = 0;
            mBounceFlag = 0;
        }
        // 1/3~2/3 画椭圆；在2/3时，切线刚好为view底部
        else if (percent < (2.0f / 3)) {
            centerY = getHeight() - posY / 2.f;
            scale = percent;
            horizontal = 2.f * (scale - 1.f / 3);
            mBounceFlag = 0;
        }
        // 2/3~1 画椭圆；在1时，椭圆高度刚好为view高度4/3
        else if (percent < 1.f) {
            scale = 2.f * percent - 2.f / 3;
            centerY = getHeight() - posY * 1.f / 3 / percent;
            horizontal = 2.f * (scale - 1.f / 3);
            mBounceFlag = 0;
        } else {
            // >1 开始弹跳动画：
            //椭圆顶部顶点，滑动到距view底部1/3
            //椭圆底部顶点，滑动到view底部；自定义动画绘画到圆上
            //开始画正圆动画->正圆结束后，开始弹跳动画

            startDropCircleAnimation();
            return;
        }

        //结束动画（自定义动画先消失，然后圆形上移收起）


//        Logger.log(TAG, "onUIPositionChange-After", "percent=" + percent + " posY=" + posY + " centerY=" + centerY + " scale=" + scale + " vertical=" + vertical + " horizontal=" + horizontal);

        mScaleCircleAnimator = ValueAnimator.ofFloat(scale, scale);
        mDropCircleAnimator = ValueAnimator.ofFloat(centerY, centerY);
//        mDropBounceVerticalAnimator = ValueAnimator.ofFloat(vertical, vertical);
        mDropBounceHorizontalAnimator = ValueAnimator.ofFloat(horizontal, horizontal);
        mScaleCircleAnimator.start();
        mDropCircleAnimator.start();
        mDropBounceVerticalAnimator.start();
        mDropBounceHorizontalAnimator.start();
        invalidate();
    }
    //endregion
}
